昨天吃太飽...成吉思汗蒙古烤肉的東西還蠻不錯吃,一不小心就吃太多。只是雖然搬了新家,地方似乎不是很大,裝潢也很樸素XD
今天電很夠,所以還是先到家附近的咖啡店寫作業。然後座位對面似乎是民眾黨的人物?電話都在解釋...
今天還是繼續調整程式架構,並且開始寫測試。還是覺得咖啡店冷氣太冷,撐了兩個鐘頭就敗退...好,下午繼續,中午吃個自助餐吧。
下午繼續,先裝好mocha跟chai然後寫個簡單用例來跑跑看:
const mocha = require('mocha');
const assert = require('chai').assert;
const xml2json = require('../lib/xml2json.js')
const teststr = '<?xml version="1.0" encoding="utf-8"?><aas:aasenv xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:IEC61360="http://www.admin-shell.io/IEC61360/2/0" xsi:schemaLocation="http://www.admin-shell.io/aas/2/0 AAS.xsd http://www.admin-shell.io/IEC61360/2/0 IEC61360.xsd" xmlns:aas="http://www.admin-shell.io/aas/2/0"><aas:assetAdministrationShells><aas:assetAdministrationShell><aas:idShort>TypeAAS</aas:idShort><aas:description><aas:langString lang="EN">AAS oft MTP type type32</aas:langString></aas:description><aas:identification idType="IRI">www.vendor.com/ids/sm/6233_9041_1002_7102</aas:identification><aas:assetRef><aas:keys><aas:key type="Asset" local="true" idType="IRI">http://vendor.com/module-types/type32</aas:key></aas:keys></aas:assetRef><aas:submodelRefs><aas:submodelRef><aas:keys><aas:key type="Submodel" local="true" idType="IRI">www.vendor.com/ids/sm/6233_9041_1002_7102</aas:key></aas:keys></aas:submodelRef><aas:submodelRef><aas:keys><aas:key type="Submodel" local="true" idType="IRI">www.vendor.com/ids/sm/5324_9041_1002_7612</aas:key></aas:keys></aas:submodelRef></aas:submodelRefs><aas:conceptDictionaries /></aas:assetAdministrationShell><aas:assetAdministrationShell><aas:idShort>InstanceAAS</aas:idShort><aas:identification idType="IRI">www.vendor.com/ids/sm/6233_9041_1002_7103</aas:identification><aas:derivedFrom><aas:keys><aas:key type="AssetAdministrationShell" local="true" idType="IRI">www.vendor.com/ids/sm/6233_9041_1002_7102</aas:key></aas:keys></aas:derivedFrom><aas:assetRef><aas:keys><aas:key type="Asset" local="true" idType="IRI">http://vendor.com/module/4711</aas:key></aas:keys></aas:assetRef><aas:submodelRefs><aas:submodelRef><aas:keys><aas:key type="Submodel" local="true" idType="IRI">www.vendor.com/ids/sm/4594_9041_1002_9069</aas:key></aas:keys></aas:submodelRef><aas:submodelRef><aas:keys><aas:key type="Submodel" local="true" idType="IRI">www.vendor.com/ids/sm/8115_9041_1002_3217</aas:key></aas:keys></aas:submodelRef></aas:submodelRefs><aas:conceptDictionaries /></aas:assetAdministrationShell></aas:assetAdministrationShells></aas:aasenv>';
describe('starting', () => {
describe('add Asset Administration Shell', () => {
it('test convert xml to json', () => {
let obj = xml2json(teststr);
let shouldbe = '{"xml":{},"aasenv":{"xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance","xmlns:IEC61360":"http://www.admin-shell.io/IEC61360/2/0","xsi:schemaLocation":"http://www.admin-shell.io/aas/2/0 AAS.xsd http://www.admin-shell.io/IEC61360/2/0 IEC61360.xsd","xmlns:aas":"http://www.admin-shell.io/aas/2/0","assetAdministrationShells":[{"idShort":"TypeAAS","description":[{"lang":"EN","_value":"AAS oft MTP type type32"}],"identification":{"idType":"IRI","_value":"www.vendor.com/ids/sm/6233_9041_1002_7102"},"assetRef":{"keys":[{"type":"Asset","local":"true","idType":"IRI","_value":"http://vendor.com/module-types/type32"}]},"submodelRefs":[{"keys":[{"type":"Submodel","local":"true","idType":"IRI","_value":"www.vendor.com/ids/sm/6233_9041_1002_7102"}]},{"keys":[{"type":"Submodel","local":"true","idType":"IRI","_value":"www.vendor.com/ids/sm/5324_9041_1002_7612"}]}],"conceptDictionaries":[]},{"idShort":"InstanceAAS","identification":{"idType":"IRI","_value":"www.vendor.com/ids/sm/6233_9041_1002_7103"},"derivedFrom":{"keys":[{"type":"AssetAdministrationShell","local":"true","idType":"IRI","_value":"www.vendor.com/ids/sm/6233_9041_1002_7102"}]},"assetRef":{"keys":[{"type":"Asset","local":"true","idType":"IRI","_value":"http://vendor.com/module/4711"}]},"submodelRefs":[{"keys":[{"type":"Submodel","local":"true","idType":"IRI","_value":"www.vendor.com/ids/sm/4594_9041_1002_9069"}]},{"keys":[{"type":"Submodel","local":"true","idType":"IRI","_value":"www.vendor.com/ids/sm/8115_9041_1002_3217"}]}],"conceptDictionaries":[]}]}}';
assert(JSON.stringify(obj) === shouldbe, 'ok');
});
})
});
然後改一下package.json
,把下面這行:
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
改成:
"scripts": {
"test": "node_modules/.bin/mocha tests"
},
然後執行:
npm test
就可以看到結果:
fillano$ npm test
> aasserv@1.0.0 test /Users/fillano/builds/aasserv
> mocha tests
starting
add Asset Administration Shell
✓ test convert xml to json
1 passing (24ms)
確認可以跑出結果,就可以繼續下去。istanbul
就等後面再來改。
結果傍晚意外陷入昏睡,還好九點醒來了,沒錯過發文
接下來還是看一下處理pptx viewer的程式...
<!DOCTYPE html>
<html>
<head>
<title>file reader</title>
<style>
.dropable {
width: 99%;
height: 100px;
background-color: #369;
color: white;
border: solid 3px gray;
border-radius: 5px;
padding: 5px 5px 5px 5px;
}
.message {
width: 99%;
background-color: #ddd;
border: solid 1px gray;
border-radius: 5px;
overflow: auto;
}
.preview {
font-size: 10px;
}
</style>
</head>
<body>
<div id="target" class="dropable">
<select id="encoding">
<option value="utf-8">utf-8</option>
<option value="big5">big5</option>
<option value="gb2312">gb2312</option>
<option value="shift-jis">shift-jis</option>
</select>
<input type="file" id="file" />
<div id="console"></div>
</div>
<div id="panel" class="message"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pako/1.0.11/pako_inflate.min.js"></script>
<script src="lib/zipfs.js"></script>
<script src="node_modules/xmlrun/index.js"></script>
<script>
var _target = document.getElementById('target');
var _message = document.getElementById('panel');
var _file = document.getElementById('file');
_file.onchange = function(e) {
clearlog();
if (this.files.length > 0) {
var reader = new FileReader();
reader.onload = (e) => {
var buffer = e.target.result;
log('file size: ' + buffer.byteLength);
let encoding = document.getElementById('encoding').value;
let start = new Date().getTime();
zipfs(buffer, pako.inflateRaw, encoding, (err, files) => {
if (!!err) return console.log(err);
log(`in callback: ${files.length} files extracted.`);
log(`${(new Date().getTime()-start)} ms`);
let str = '<table border="1" cellspacing="0" cellpadding="5" width="99%"><tr><th>file name</th><th>buffer length</th><th>last modified date</th><th>last modified time</th><th>compressed size</th><th>uncompressed size</th></tr>';
files.forEach(file => {
str += `<tr><td>${file.file_name}</td><td>${file.content.length}</td><td>${zipfs.formatMSDOSDate(file.last_modified_date)}</td><td>${zipfs.formatMSDOSTime(file.last_modified_time)}</td><td>${file.compressed_size}</td><td>${file.uncompressed_size}</td></tr>`;
str += `<tr><td colspan="6" class="preview" style="overflow-x:hidden">`;
if (checkExt(file.file_name, '.rels')/* && file.file_name.split('/')[file.file_name.split('/').length-1].length > 5*/) {
console.log(file.file_name);
let runner = xmlnode(zipfs.uintToString(file.content));
runner.setRunner('default', function(target) {
if(!!target.child) {
return target.child.reduce((acc, cur) => {
Object.assign(acc, cur.run());
return acc;
}, {})
}
else return {};
});
runner.setRunner('Relationship', target => {
let result = {};
result[target.attr['Id']] = target.attr['Target'];
result[target.attr['Target']] = target.attr['Id'];
return result;
});
let obj = runner.run();
str += `<pre>${JSON.stringify(obj, null, 2)}</pre>`;
}
if (checkExt(file.file_name, '.xml')) {
let runner = xmlnode(zipfs.uintToString(file.content));
runner.setRunner('default', function(target) {
let result = {
type: xmlnode.utils.getNodeTypeDesc(target.type),
tagName: target.tag,
attributes: target.attr,
value: target.val,
children: []
}
if(!!target.child) {
result.children = target.child.reduce((acc, cur) => {
acc.push(cur.run());
return acc;
}, []);
}
return result;
});
let obj = runner.run();
str += `<pre>${JSON.stringify(obj, null, 2)}</pre>`;
}
if (checkExt(file.file_name, '.jpeg') || checkExt(file.file_name, '.jpg')) {
let im = new Image();
im.src = `data:image/jpeg;base64,${zipfs.arrayBufferToBase64(file.content)}`;
if(im.width > 1024) {
str += `<img width="1024px" src="data:image/jpeg;base64,${zipfs.arrayBufferToBase64(file.content)}">`;
} else {
str += `<img src="data:image/jpeg;base64,${zipfs.arrayBufferToBase64(file.content)}">`;
}
}
if (checkExt(file.file_name, '.png')) {
let im = new Image();
im.src = `data:image/png;base64,${zipfs.arrayBufferToBase64(file.content)}`;
if(im.width > 1024) {
str += `<img width="1024px" src="data:image/png;base64,${zipfs.arrayBufferToBase64(file.content)}">`;
} else {
str += `<img src="data:image/png;base64,${zipfs.arrayBufferToBase64(file.content)}">`;
}
}
if (checkExt(file.file_name, '.mp3')) {
str += '<audio controls type="audio/mpeg" src="data:audio/mp3;base64,' +
zipfs.arrayBufferToBase64(file.content) + '">';
}
str += '</td></tr>';
});
str += '</table>';
document.getElementById('panel').innerHTML = str;
});
};
reader.readAsArrayBuffer(this.files[0]);
}
function checkExt(name, ext) {
return name.lastIndexOf(ext) === name.length - ext.length;
}
function log(msg) {
document.getElementById('console').innerHTML += `<br />${msg}`;
}
function clearlog() {
document.getElementById('console').innerHTML = '';
}
}
</script>
</body>
</html>
先來處理.rels
檔,其內容如昨天所說的,就是一個id與目標檔案的對照,所以增加一個針對.rels
檔處理內容的程式,結果一般xml檔顯示:
如果是.rels
檔,就會特別處理:
好了,本日quota已經達到(剛剛程式忘了呼叫某遞迴函數,找問題找了好久...),先休息了。